/******************************************************************************
//             INTEL CORPORATION PROPRIETARY INFORMATION
//  This software is supplied under the terms of a license agreement or
//  nondisclosure agreement with Intel Corporation and may not be copied
//  or disclosed except in accordance with the terms of that agreement.
//        Copyright (c) 2000-2001 Intel Corporation. All Rights Reserved.
//
//  Description:
//      Intel(R) JPEG library for X platform 
//
********************************************************************************/
#include "_ijx.h"

/* Default Luminance Quantization Table */
Ipp16s _DefLumQuantTable[64] =
{
    16,	11,	10,	16,	24,  40,  51,  61,
    12,	12,	14,	19,	26,  58,  60,  55,
    14,	13,	16,	24,	40,  57,  69,  56,
    14,	17,	22,	29,	51,  87,  80,  62,
    18,	22,	37,	56,	68,  109, 103, 77,
    24,	35,	55,	64,	81,  104, 113, 92,
    49,	64,	78,	87,	103, 121, 120, 101,
    72,	92,	95,	98,	112, 100, 103, 99
};

/* Default Chrominance Quantization Table */
Ipp16s _DefChromQuantTable[64] =
{
    17,	18,	24,	47,	99,	99,	99,	99,
    18,	21,	26,	66,	99,	99,	99,	99,
    24,	26,	56,	99,	99,	99,	99,	99,
    47,	66,	99,	99,	99,	99,	99,	99,
    99,	99,	99,	99,	99,	99,	99,	99,
    99,	99,	99,	99,	99,	99,	99,	99,
    99,	99,	99,	99,	99,	99,	99,	99,
    99,	99,	99,	99,	99,	99,	99,	99
};

/* Default Luminance DC bits of huffman table specification */
Ipp8u _DefLumDCHuffBits[] =
{
  0x00, 0x01, 0x05, 0x01, 0x01, 0x01, 0x01, 0x01,
  0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
};

/* Default Luminance DC values of huffman table specification */
Ipp8u _DefLumDCHuffValues[] =
{
  0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
  0x08, 0x09, 0x0a, 0x0b
};


/* Default Chrominance DC bits of huffman table specification */
Ipp8u _DefChromDCHuffBits[] =
{
  0x00, 0x03, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
  0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00
};


/* Default Chrominance DC values of huffman table specification */
Ipp8u _DefChromDCHuffValues[] =
{
  0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
  0x08, 0x09, 0x0a, 0x0b
};


/* Default Luminance AC Bits of huffman table specification */
Ipp8u _DefLumACHuffBits[] =
{
  0x00, 0x02, 0x01, 0x03, 0x03, 0x02, 0x04, 0x03,
  0x05, 0x05, 0x04, 0x04, 0x00, 0x00, 0x01, 0x7d
};


/* Default Luminance AC values of huffman table specification */
Ipp8u _DefLumACHuffValues[] =
{
  0x01, 0x02, 0x03, 0x00, 0x04, 0x11, 0x05, 0x12,
  0x21, 0x31, 0x41, 0x06, 0x13, 0x51, 0x61, 0x07,
  0x22, 0x71, 0x14, 0x32, 0x81, 0x91, 0xa1, 0x08,
  0x23, 0x42, 0xb1, 0xc1, 0x15, 0x52, 0xd1, 0xf0,
  0x24, 0x33, 0x62, 0x72, 0x82, 0x09, 0x0a, 0x16,
  0x17, 0x18, 0x19, 0x1a, 0x25, 0x26, 0x27, 0x28,
  0x29, 0x2a, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39,
  0x3a, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, 0x49,
  0x4a, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58, 0x59,
  0x5a, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69,
  0x6a, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, 0x79,
  0x7a, 0x83, 0x84, 0x85, 0x86, 0x87, 0x88, 0x89,
  0x8a, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97, 0x98,
  0x99, 0x9a, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7,
  0xa8, 0xa9, 0xaa, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6,
  0xb7, 0xb8, 0xb9, 0xba, 0xc2, 0xc3, 0xc4, 0xc5,
  0xc6, 0xc7, 0xc8, 0xc9, 0xca, 0xd2, 0xd3, 0xd4,
  0xd5, 0xd6, 0xd7, 0xd8, 0xd9, 0xda, 0xe1, 0xe2,
  0xe3, 0xe4, 0xe5, 0xe6, 0xe7, 0xe8, 0xe9, 0xea,
  0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, 0xf8,
  0xf9, 0xfa
};


/* Default Chrominance AC Bits of huffman table specification */
Ipp8u _DefChromACHuffBits[] =
{
  0x00, 0x02, 0x01, 0x02, 0x04, 0x04, 0x03, 0x04,
  0x07, 0x05, 0x04, 0x04, 0x00, 0x01, 0x02, 0x77
};


/* Default Chrominance AC values of huffman table specification */
Ipp8u _DefChromACHuffValues[] =
{
  0x00, 0x01, 0x02, 0x03, 0x11, 0x04, 0x05, 0x21,
  0x31, 0x06, 0x12, 0x41, 0x51, 0x07, 0x61, 0x71,
  0x13, 0x22, 0x32, 0x81, 0x08, 0x14, 0x42, 0x91,
  0xa1, 0xb1, 0xc1, 0x09, 0x23, 0x33, 0x52, 0xf0,
  0x15, 0x62, 0x72, 0xd1, 0x0a, 0x16, 0x24, 0x34,
  0xe1, 0x25, 0xf1, 0x17, 0x18, 0x19, 0x1a, 0x26,
  0x27, 0x28, 0x29, 0x2a, 0x35, 0x36, 0x37, 0x38,
  0x39, 0x3a, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48,
  0x49, 0x4a, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58,
  0x59, 0x5a, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68,
  0x69, 0x6a, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78,
  0x79, 0x7a, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87,
  0x88, 0x89, 0x8a, 0x92, 0x93, 0x94, 0x95, 0x96,
  0x97, 0x98, 0x99, 0x9a, 0xa2, 0xa3, 0xa4, 0xa5,
  0xa6, 0xa7, 0xa8, 0xa9, 0xaa, 0xb2, 0xb3, 0xb4,
  0xb5, 0xb6, 0xb7, 0xb8, 0xb9, 0xba, 0xc2, 0xc3,
  0xc4, 0xc5, 0xc6, 0xc7, 0xc8, 0xc9, 0xca, 0xd2,
  0xd3, 0xd4, 0xd5, 0xd6, 0xd7, 0xd8, 0xd9, 0xda,
  0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 0xe7, 0xe8, 0xe9,
  0xea, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, 0xf8,
  0xf9, 0xfa
};

/******************************************************************************
// Name:            ijAdjustStream
// Description:     Adjust stream for encoding
// Input Arguments:
//         pStream: Points to IJBITTREAMSTATE struct that defined stream buffer.
// Output Arguments:
//         pStream: updated stream buffer.
//                          
//                  
******************************************************************************/
void ijAdjustStream(IJBITTREAMSTATE *pStream)
{
    int nUsedBytes;
    Ipp8u *pBitStreamBuf;
    const int nPadBitsLen=((pStream->nUsedBufBitsLen)&7);

    if (0<nPadBitsLen) {
        nUsedBytes=((pStream->nUsedBufBitsLen)>>3);
        pBitStreamBuf=&(pStream->pBitStream)[nUsedBytes];
        *pBitStreamBuf&=(~(0XFF>>(nPadBitsLen)));
        pStream->nUsedBufBitsLen=((nUsedBytes+1)<<3);
    }
}

/******************************************************************************
// Name:            ijWriteStreamBytes
// Description:     Write bytes into stream buffer
// Input Arguments:  
//        pSrcData: Points to source data buffer.
//       nBytesLen: Number of byte to be written,
//         pStream: Points to IJBITTREAMSTATE struct that defined stream buffer.
// Output Arguments:
//         pStream: Updated stream buffer.                 
//                  
******************************************************************************/
IJXRESULT ijWriteStreamBytes(void * pSrcData, 
                             int nBytesLen,
                             IJBITTREAMSTATE *pStream)
{
    int i;
    const int nMaxBufBytes=pStream->nMaxBufLen;
    const int nPadBitsLen=((pStream->nUsedBufBitsLen)&7);
    int nUsedBytes=((pStream->nUsedBufBitsLen)>>3);
    Ipp8u *pSrcCur=(Ipp8u *)pSrcData;
    Ipp8u *pBitStreamBuf=&(pStream->pBitStream)[nUsedBytes];
    
    //IJX_ASSERT(0==((pStream->nUsedBufBitsLen)&7));
    //IJX_ASSERT(nBytesLen<(nMaxBufBytes-nUsedBytes));

    if (0!=nPadBitsLen) {
        /* suffing */
        //*pBitStreamBuf++|=(0XFF>>(nPadBitsLen));
        *pBitStreamBuf&=(~(0XFF>>(nPadBitsLen)));
        pBitStreamBuf++;
        nUsedBytes++;
        //pStream->nUsedBufBitsLen+=(8-nPadBitsLen);
    }

    if (nBytesLen>(nMaxBufBytes-nUsedBytes)) {
        return IJX_RTCODE_W_INSUFFICIENTBUF;
    }

    for (i=0; i<nBytesLen; i++) {
        *pBitStreamBuf++=*pSrcCur++;
    }

    pStream->nUsedBufBitsLen=((nUsedBytes+nBytesLen)<<3);

    return IJX_RTCODE_OK;
}

/******************************************************************************
// Name:            ijReadStreamBytes
// Description:     Read bytes from stream buffer
// Input Arguments:
//       nBytesLen: Number of bytes to be read from stream buffer.
//         pStream: Points to IJBITTREAMSTATE struct that defined stream buffer.
// Output Arguments:
//        pSrcData: Points to the read data buffer. 
//         pStream: Updated stream buffer.                 
//                          
//                  
******************************************************************************/
IJXRESULT ijReadStreamBytes(void * pSrcData, 
                            int  nBytesLen, 
                            IJBITTREAMSTATE *pStream)
{
    int i;
    const int nMaxBufBytes=pStream->nMaxBufLen;
    int nUsedBytes=((pStream->nUsedBufBitsLen+7)>>3);
    Ipp8u *pSrcCur=(Ipp8u *)pSrcData;
    Ipp8u *pBitStreamBuf=&(pStream->pBitStream)[nUsedBytes];
    
    if (nBytesLen>(nMaxBufBytes-nUsedBytes)) {
        return IJX_RTCODE_W_INSUFFICIENTBUF;
    }

    for (i=0; i<nBytesLen; i++) {
        *pSrcCur++=*pBitStreamBuf++;
    }

    pStream->nUsedBufBitsLen=((nUsedBytes+nBytesLen)<<3);

    return IJX_RTCODE_OK;
}


/******************************************************************************
// Name:            ijInitMCU
// Description:     Initialize MCU parameters
// Input Arguments:
//     nImageWidth: Specifies image width in pixel.
//    nImageHeight: Specifies image height in pixel.
//       nMCUWidth: Specifies MCU block width in pixel.
//      nMCUHeight: Specifies MCU block height in pixel.
// Output Arguments:
//        pMCUSpec: Points to IJMCUSPEC struct that defined MCU parameters.
//                          
//                  
******************************************************************************/
void ijInitMCU(int       nImageWidth,
               int       nImageHeight,
               int       nMCUWidth,
               int       nMCUHeight,
               int       nImageMCUStep,
               int       nBlksInMCU,
               int       nSubSamplingMode,
               BOOL      bMCUInterleaved,
               IJMCUSPEC *pMCUSpec)
{
    int nHCount, nVCount, nCount;


    pMCUSpec->nMCUWidth=nMCUWidth;
    pMCUSpec->nMCUHeight=nMCUHeight;
    pMCUSpec->nImageMCUStep=nImageMCUStep;

    pMCUSpec->nHMCUCount=nImageWidth/nMCUWidth;
    pMCUSpec->nVMCUCount=nImageHeight/nMCUHeight;
    pMCUSpec->nMCUPadWidth=nImageWidth-(nMCUWidth*pMCUSpec->nHMCUCount);
    pMCUSpec->nMCUPadHeight=nImageHeight-(nMCUHeight*pMCUSpec->nVMCUCount);

    if (0==pMCUSpec->nMCUPadWidth) {
        nHCount=pMCUSpec->nHMCUCount;
    } else {
        nHCount=pMCUSpec->nHMCUCount+1;
    }
    if (0==pMCUSpec->nMCUPadHeight) {
        nVCount=pMCUSpec->nVMCUCount;
    } else {
        nVCount=pMCUSpec->nVMCUCount+1;
    }
    nCount=nHCount*nVCount;
    pMCUSpec->nTotalMCUCount=nCount;

    pMCUSpec->nBlksInMCU=nBlksInMCU;

    switch (nSubSamplingMode) {
        case IIP_SM_NONE:
            if (bMCUInterleaved) {
                pMCUSpec->naBlksOffset[0]=0;
                pMCUSpec->naBlksOffset[1]=1;
                pMCUSpec->naBlksOffset[2]=1;

                pMCUSpec->naCoeffOffset[0]=nBlksInMCU*64;
            } else {
                pMCUSpec->naBlksOffset[0]=0;
                pMCUSpec->naBlksOffset[1]=nCount;
                pMCUSpec->naBlksOffset[2]=nCount;

                pMCUSpec->naCoeffOffset[0]=64;
                pMCUSpec->naCoeffOffset[1]=64;
                pMCUSpec->naCoeffOffset[2]=64;
            }
            break;
        case IIP_SM_422:
            if (bMCUInterleaved) {
                pMCUSpec->naBlksOffset[0]=0;
                pMCUSpec->naBlksOffset[1]=2;
                pMCUSpec->naBlksOffset[2]=1;

                pMCUSpec->naCoeffOffset[0]=nBlksInMCU*64;
            } else {
                pMCUSpec->naBlksOffset[0]=0;
                pMCUSpec->naBlksOffset[1]=2*nCount;
                pMCUSpec->naBlksOffset[2]=nCount;

                pMCUSpec->naCoeffOffset[0]=128;
                pMCUSpec->naCoeffOffset[1]=64;
                pMCUSpec->naCoeffOffset[2]=64;
            }
            break;
        case IIP_SM_411:
            if (bMCUInterleaved) {
                pMCUSpec->naBlksOffset[0]=0;
                pMCUSpec->naBlksOffset[1]=4;
                pMCUSpec->naBlksOffset[2]=1;

                pMCUSpec->naCoeffOffset[0]=nBlksInMCU*64;
            } else {
                pMCUSpec->naBlksOffset[0]=0;
                pMCUSpec->naBlksOffset[1]=4*nCount;
                pMCUSpec->naBlksOffset[2]=nCount;

                pMCUSpec->naCoeffOffset[0]=256;
                pMCUSpec->naCoeffOffset[1]=64;
                pMCUSpec->naCoeffOffset[2]=64;
            }
            break;
        default:
            break;
    }
}

/******************************************************************************
// Name:            ijInitComponentSpec
// Description:     Initialize Component parameters
// Input Arguments:
//     nIdentifier: Specifies component index in radix 0. 
//      nHSampling: Specifies resampling factor in Horizontal. 
//      nVSampling: Specifies resampling factor in Vertical.
//     nQuantIndex: Specifies Quatizantion Table index used for this component.
// nDCHuffTableIndex: 
//                  Specifies DC Huffman Table index used for this component.
// nACHuffTableIndex: 
//                  Specifies AC Huffman Table index used for this component.
// Output Arguments:
//        pMCUSpec: Points to IJCOMPSPEC struct that defined component parameters.
//                  
******************************************************************************/
void ijInitComponentSpec(int nIdentifier, 
                         int nHSampling, 
                         int nVSampling, 
                         int nQuantIndex, 
                         int nDCHuffTableIndex, 
                         int nACHuffTableIndex,
                         IJCOMPSPEC *pCompSpec)
{
    pCompSpec[nIdentifier].nIdentifier=nIdentifier;
    pCompSpec[nIdentifier].nHSampling=nHSampling;
    pCompSpec[nIdentifier].nVSampling=nVSampling;
    pCompSpec[nIdentifier].nNumDataUnit=nHSampling*nVSampling;
    pCompSpec[nIdentifier].nQuantTableIndex=nQuantIndex;
    pCompSpec[nIdentifier].nDCHuffTableIndex=nDCHuffTableIndex;
    pCompSpec[nIdentifier].nACHuffTableIndex=nACHuffTableIndex;
}

/******************************************************************************
// Name:            ijInitFrameComponents
// Description:     Initialize all components defined in a frame
// Input Arguments:
//        nNumComp: Specifies number of components defined in a frame.
// Output Arguments:
//       pCompSpec: Points to a array of  IJCOMPSPEC struct that 
//                  defined all component parameters in a frame.
//                          
//                  
******************************************************************************/
void ijInitFrameComponents(int nNumComp,
                           IJCOMPSPEC *pCompSpec)
{
    int i;
    int nHSampling, nVSampling;

    for (i=0; i<nNumComp; i++) {
        nHSampling=pCompSpec[i].nHSampling;
        nVSampling=pCompSpec[i].nVSampling;
        pCompSpec[i].nNumDataUnit=nHSampling*nVSampling;
    }
}



/******************************************************************************
// Name:            ijInitBuffers
// Description: Initial IJBUFFER structure.         
// Input Arguments:
//         pBufPtr: Points to the internal buffer which allocated by codec caller. 
//         nBufLen: Specifies buffer length in byte which was identified by pBufPtr.
//        pMCUSpec: Points to IJMCUSPEC structure that defined MCU information.
//      pImageSpec: Points to IIPIMAGESPEC structure that defined Image information.
// Output Arguments:
//         pBuffer: Points to IJBUFFER structure that defined all buffers used in this codec  
//                          
// Returns:          
******************************************************************************/
IJXRESULT ijInitBuffers(void         *pBufPtr, 
                        int          nBufLen,
                        IJBUFFER     *pBuffer,
                        IJMCUSPEC    *pMCUSpec,
                        IIPIMAGESPEC *pImageSpec)
{
    int          i;
    unsigned int address;
    Ipp16s       *pCoeffBuffer;

    if (nBufLen<pBuffer->nMaxBufLen) {
        return IJX_RTCODE_E_ERRPARAM;
    }

    address      = (unsigned int)IIP_ALIGN_32B(pBufPtr);
    pCoeffBuffer = (Ipp16s *)address;
    
    //IJX_ASSERT(address>=(unsigned int)pBufPtr);

    switch (pBuffer->nFlag) {
        case IJX_JPEGBUFMODE_MCUORIMGCOEFF    :
            /* 
            // Coeff buffer is same as MCU buffer 
            // Coeff buffer size is equal to one MCU size
            */
            for (i=0; i<pImageSpec->nNumComponent; i++) {
                pCoeffBuffer+=((pMCUSpec->naBlksOffset[i])<<6);
                pBuffer->paMCUCoeffBuf[i]    = pCoeffBuffer;
                pBuffer->paImgCoeffBuf[i]    = pCoeffBuffer;
                pBuffer->paMCUCoeffBufCur[i] = pCoeffBuffer;
                pBuffer->paImgCoeffBufCur[i] = pCoeffBuffer;
            }
            break;
        case IJX_JPEGBUFMODE_MCUANDIMGCOEFF:
            /* 
            // Coeff buffer is equal to whole image size
            // MCU buffer size is equal to one MCU size
            */
            for (i=0; i<pImageSpec->nNumComponent; i++) {
                pBuffer->paMCUCoeffBuf[i]=pCoeffBuffer;
                pBuffer->paMCUCoeffBufCur[i]=pCoeffBuffer;
                pCoeffBuffer+=(pMCUSpec->naCoeffOffset[i]);
            }
            for (i=0; i<pImageSpec->nNumComponent; i++) {
                pCoeffBuffer+=((pMCUSpec->naBlksOffset[i])<<6);
                pBuffer->paImgCoeffBuf[i]=pCoeffBuffer;
                pBuffer->paImgCoeffBufCur[i]=pCoeffBuffer;
            }
            break;
        case IJX_JPEGBUFMODE_MCUIMGCOEFFSHARE :
            /* 
            // Coeff buffer is equal to whole image size
            // MCU buffer size is equal to one MCU size
            */
            for (i=0; i<pImageSpec->nNumComponent; i++) {
                pBuffer->paMCUCoeffBuf[i]=pCoeffBuffer;
                pBuffer->paMCUCoeffBufCur[i]=pCoeffBuffer;
                pCoeffBuffer+=(pMCUSpec->naCoeffOffset[i]);
            }
            pCoeffBuffer = (Ipp16s *)address;
            for (i=0; i<pImageSpec->nNumComponent; i++) {
                pCoeffBuffer+=((pMCUSpec->naBlksOffset[i])<<6);
                pBuffer->paImgCoeffBuf[i]=pCoeffBuffer;
                pBuffer->paImgCoeffBufCur[i]=pCoeffBuffer;
            }
            break;
        default:
            return IJX_RTCODE_ERROR;
    }

    if (pBuffer->nAuxBufLen) {
        address=IIP_ALIGN_32B(address+pBuffer->nCoeffBufLen);
        pBuffer->pAuxMCUDataTempBuf=(Ipp8u *)address;
        pBuffer->pAuxFreqBuf=(int *)address;
    }


    return IJX_RTCODE_OK;
}

/******************************************************************************
// Name:            ijResetBuffers
// Description:     Reset work buffer points.
// Input Arguments:
// Output Arguments:
//       pIJXBuffer:Points to the IJBUFFER structure that defined all buffers used in this codec
//                     
//                  
******************************************************************************/
void ijResetBuffers(IJBUFFER *pIJXBuffer)
{
    pIJXBuffer->paMCUCoeffBufCur[0]=pIJXBuffer->paMCUCoeffBuf[0];
    pIJXBuffer->paMCUCoeffBufCur[1]=pIJXBuffer->paMCUCoeffBuf[1];
    pIJXBuffer->paMCUCoeffBufCur[2]=pIJXBuffer->paMCUCoeffBuf[2];
    pIJXBuffer->paMCUCoeffBufCur[3]=pIJXBuffer->paMCUCoeffBuf[3];

    pIJXBuffer->paImgCoeffBufCur[0]=pIJXBuffer->paImgCoeffBuf[0];
    pIJXBuffer->paImgCoeffBufCur[1]=pIJXBuffer->paImgCoeffBuf[1];
    pIJXBuffer->paImgCoeffBufCur[2]=pIJXBuffer->paImgCoeffBuf[2];
    pIJXBuffer->paImgCoeffBufCur[3]=pIJXBuffer->paImgCoeffBuf[3];

    pIJXBuffer->paImageBufCur[0]=pIJXBuffer->paImageBuf[0];
    pIJXBuffer->paImageBufCur[1]=pIJXBuffer->paImageBuf[1];
    pIJXBuffer->paImageBufCur[2]=pIJXBuffer->paImageBuf[2];
    pIJXBuffer->paImageBufCur[3]=pIJXBuffer->paImageBuf[3];
}

/* EOF */
